#include <inttypes.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>

#define TEST(format, args...)                                                  \
    {                                                                          \
        int n1, n2;                                                            \
        n1 = printf(format, ##args);                                           \
        n2 = my_printf(format, ##args);                                        \
        printf("n1 = %d, n2 = %d\n", n1, n2);                                  \
    }

#define PUTC(c) putchar(c), cnt += 1

int output_int(int num)
{
    int cnt = 0;
    int flag = (num < 0);
    int8_t arr[20];
    int len = 0;

    //为了解决字符0所产生的不输出错误，使用do-while
    do {
        arr[len] = num % 10;
        num /= 10;
        len += 1;
    } while (num);

    if (flag)
        PUTC('-');
    for (int j = len - 1; j >= 0; j--) {
        // printf("%d", arr[j]);    看看bug出在哪
        if (flag)
            PUTC((-arr[j] + '0'));
        else
            PUTC(arr[j] + '0');
    }
    return cnt;
}

char base_16_code(unsigned int x)
{
    if (x < 10)
        return x + '0';
    return x - 10 + 'a';
}

int output_int_hex(unsigned int num)
{
    int cnt = 0, len = 0;
    int8_t arr[20];
    do {
        arr[len++] = num % 16;
        num /= 16;
    } while (num);
    for (int i = len - 1; i >= 0; i--) {
        PUTC(base_16_code(arr[i]));
    }
    return cnt;
}

int my_printf(const char* format, ...)
{

    va_list arg;
    va_start(arg, format);
    int cnt = 0;
    for (int i = 0; format[i]; i++) {
        switch (format[i]) {
        case '%': {
            switch (format[++i]) {
            case '%': {
                PUTC('%');
                // i += 1;
            } break;
            case 's': {
                const char* s = va_arg(arg, char*);
                for (int j = 0; s[j]; j++)
                    PUTC(s[j]);
                // i += 1;
            } break;
            case 'd': {
                int num = va_arg(arg, int);
                cnt += output_int(num);
                // i++;
            } break;
            case 'x': {
                unsigned int num = va_arg(arg, unsigned int);
                cnt += output_int_hex(num);
                // i++;
            } break;
            }
            // i += 1;
        } break;
        default:
            PUTC(format[i]);
            break;
        }
    }

#undef PUTC
    return cnt;
}

int main()
{
    TEST("hello world\n");
    TEST("100%%\n");
    TEST("%s", "hello world 100%%\n");
    TEST("INT32_MAX = %d, INT32_MIN = %d\n", INT32_MAX, INT32_MIN);
    TEST("zero = %d\n", 0);
    TEST("123 = %x, -1 = %x, INT32_MIN = %x\n", 123, -1, INT32_MIN);
    return 0;
}